package com.example.nio;

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;

public class NIOServer {
    public static void main(String[] args) throws Exception{
        // 启用sever、设置端口，建立绑定关系
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        InetSocketAddress inetSocketAddress = new InetSocketAddress(6666);
        serverSocketChannel.socket().bind(inetSocketAddress);
        serverSocketChannel.configureBlocking(false);
        // 启用selector
        Selector selector = Selector.open();
        // serverSocketChannel注册到selector
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        // 循环处理客户端的连接
        while (true){
            // 每秒获取一次事件
            if (selector.select(1000) == 0){
                System.out.println("服务器等待了1s，无连接");
                continue;
            }
            // 获取所有活动事件的key
            Set<SelectionKey> selectionKeys = selector.selectedKeys();
            Iterator<SelectionKey> selectionKeyIterator = selectionKeys.iterator();
            while (selectionKeyIterator.hasNext()){
                // 通过selector获取活动的key
                SelectionKey selectionKey = selectionKeyIterator.next();
                // 如果是客户端第一次建立连接，则把客户端socketChannel和selector建立绑定关系
                if (selectionKey.isAcceptable()){
                    SocketChannel socketChannel = serverSocketChannel.accept();
                    //将socketChannel设置为非阻塞的
                    socketChannel.configureBlocking(false);
                    System.out.println("客户端建立成功，channelHash:" + socketChannel.hashCode());
                    // 注册到selector上，同时管理buffer并设置大小
                    socketChannel.register(selector, SelectionKey.OP_READ, ByteBuffer.allocate(1024));
                }

                // 如果是发送消息，则
                if (selectionKey.isReadable()){
                    // 向下转型，方便使用子类中特有的方法
                    SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
                    ByteBuffer byteBuffer = (ByteBuffer) selectionKey.attachment();
                    socketChannel.read(byteBuffer);
                    System.out.println("from 客户端：" + new String(byteBuffer.array()));
                }
                // 当前事件处理完记得移除，避免重复执行
                selectionKeyIterator.remove();
            }
        }


    }
}
